(function($, window, document){
	var MENUCLASS = "keyboard-hotkey-menu";		// css class using in addByList()
	var LEVEL = "keyboard-hotkey-level";
	var ACTIVE = "active";
	var DEACTIVE = "deactive";
	var DS = "_ds_";
	var G_hotkey = {};
	var G_cache=false;
	var ram = {
		debug : $.keyboard.debug,
		add : function(){								// add key's to the fnlist on keyboard
			var _label = arguments[0];
			var _tmplist = ram.download();				// we don't know $.keyboard.bind 's function will change to what style.
			$.keyboard.reset();							// empty current hotkey
			
			for(var i=1;i<arguments.length;i++){
				$.keyboard.bind(arguments[i]);			// import keylist & wait for finish.
			}//for
			
			if( typeof G_hotkey[_label]=="undefined" ){
				G_hotkey[_label]=ram.download();		// new keylist
			}else{
				// for some reason, need to bind key in different area. we join them together.
				G_hotkey[_label] = $.merge( G_hotkey[_label], ram.download());
			}//if
			$.keyboard.reset();
			ram.load(_tmplist);							// make everything unchange.
			_tmplist="";
		},
		addByList : function(_id){
			var _target = $("#"+_id).find("ul").first();
			_target.each(function(_no){
				_target.addClass(MENUCLASS);
				_target.find("li").addClass(LEVEL);
				_target.find("ul").removeClass(ACTIVE).addClass(DEACTIVE);
				_target.first().removeClass(DEACTIVE).addClass(ACTIVE);
				if(_no==0)_no="";
				ram._levelInit(_target, _id+_no );		// init this level
			});//each
		},
		_levelInit : function(_target, _path){
			// _target = ul
			_target.find(">li").each(function(_no){
				ram._itemInit( $(this) , _path );
			});
			/**
			// non-DOM version - submenu
			if( typeof _key!="undefined" ){
				var _parent = _path.split(DS);
				_parent.pop()
				_parent=_parent.join(DS);
				ram.debug("level Init key="+_key +", _parent="+ _parent);
				ram.add(_parent ,{
					key : _key,
					fn : function(){
						ram.debug("load submenu : "+ _path );
						ram.load( _path, true );
						$("#"+_path).find(">ul").removeClass(DEACTIVE).addClass(ACTIVE);
					}
				});
			}//if
			//*/
		},
		_itemInit : function(_item, _path){
			// _item = li
			var _key = _item.attr("key");
			var _id = (_path+DS+_key).toLowerCase();
			_id = _id.replace(/(\W)/gi, "");					// fix : id can't not be special char
			var _fn = _item.attr("fn");
			_item.attr("id" , _id ).removeAttr("key").removeAttr("fn");
			if( typeof _fn=="undefined" ) _fn="";
			_item.click(function(event){
				event.preventDefault();
				event.stopPropagation();
				if( $.trim(_fn)!="" ){ eval( _fn );}
			});	// assign id & function click to element.
			ram.debug("-- item Init key="+_key +", on path="+ _path);
			ram.add(_path,{
				key : _key,
				fn : function(){
					$("#"+ _id ).triggerHandler('click');
					ram.debug("item click : "+ _key +", on path="+_path);
				}
			});
			_item.find(">ul").each(function(_no){	// if contain the submenu.
				if(_no==0)_no="";
				ram._levelInit( $(this) , _id+_no);
				
				// DOM version - submenu
				_item.click(function(event){
					event.preventDefault();
					event.stopPropagation();
					ram.debug("load submenu : "+ _id+_no );
					ram._cacheMenuList();
					ram.load( _id+_no, true );
					_item.find(">ul").removeClass(DEACTIVE).addClass(ACTIVE);
				});
			});
			if( _item.find(">ul").length==0 ){	// this is the last node. after active, reset menu.
				_item.click(function(event){
					$(document).triggerHandler('resetKeyboard');
				});
			}//if
		},
		_cacheMenuList : function(){
			if( typeof G_cache=="boolean" ){
				G_cache = ram.download();	// cache my list.
				ram.debug("cacheMenuList : backup");
				$(document).unbind("resetKeyboard");
				$(document).click(function(){ $(document).triggerHandler('resetKeyboard'); });	// click outside, reset
				$(document).bind("resetKeyboard",function(event){
					event.preventDefault();
					event.stopPropagation();
					ram.load(G_cache, true);	// restore all hotkey
					$("."+MENUCLASS).find("ul").removeClass(ACTIVE).addClass(DEACTIVE);
					$("."+MENUCLASS).removeClass(DEACTIVE).addClass(ACTIVE);
					ram.debug("cacheMenuList : restore complete");
					G_cache=false;
					$(document).unbind("resetKeyboard");
				});
			}//if
			//**
			// What I want to do is :  when the menu active, visitor press ESC can be return to normal keyset.
			// do it in next loop.. by setTimeout=0, well the menu is over everything will be reset.... wfc..
			setTimeout(function(){
				$.keyBind({
					key : "esc",
					fn : function(){ $(document).triggerHandler('resetKeyboard'); }
				});
			}, 0);
			//**/
		},
		list : function(){
			var _list = [];
			for(var x in G_hotkey){
				_list.push( x );
			}//for
			return _list;
		},
		load : function(_label, _alone){
			// load the keyset form G_hotkey.
			// reset and upload.
			if(typeof _alone=="undefined")_alone=false;
			if(_alone){
				// overwrite
				if(typeof _label=="object") $.keyboard.importList(_label);
				else if(typeof G_hotkey[_label]!="undefined") $.keyboard.importList( G_hotkey[_label] );
			}else{
				// apply not overwrite
				if(typeof _label=="object"){
					$.keyboard.importList( $.merge(_label, ram.download() ));
				}else if(typeof G_hotkey[_label]!="undefined") $.keyboard.importList( $.merge(G_hotkey[_label], ram.download()) );
			}//if
		},
		download : function(){
			// download current keyboard bind function list on $.keyboard.
			return $.keyboard.exportList();
		}
	};
	
	var api = {
		add : ram.add,
		addByList : ram.addByList,
		load : ram.load,
		download : ram.download,
		list : ram.list
	};
	
	//
	// jquery redirection
	//
	$.extend({
		hotkey : api
	});
})(jQuery, window, document);  // inject global jQuery object